from django.contrib.auth.models import *
from django.db import models
import datetime


# Create your models here.
class Account(models.Model):
    user = models.OneToOneField(User)
    organization = models.ManyToManyField('Organization')
    phone = models.CharField(max_length=255)
    description = models.CharField(max_length=255)
    deleted = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)
    last_update = models.DateTimeField(auto_now=True, db_index=True)
    def is_admin(self):
        return self.admin

    def is_platform_user(self):
        try:
            return not self.admin and self.organization.all()[0].type == 0
        except:
            return False

    def is_vendor_user(self):
        try:
            return self.organization.all()[0].type == 1
        except:
            return False

    def is_merchant_user(self):
        try:
            return self.organization.all()[0].type == 2
        except:
            return False

    def get_organization(self):
        try:
            org = self.organization.all()[0]
        except:
            org = None
        return org

class Organization(models.Model):
    TYPES = (
        (0, 'Platform'),
        (1, 'Vendor'),
        (2, 'Merchant'),
    )
    name = models.CharField(max_length=256)
    deleted = models.BooleanField(default=False)
    description = models.CharField(max_length=1024, null=True)
    # balance = models.FloatField(default=0)
    in_balance = models.FloatField(default=0)
    out_balance = models.FloatField(default=0)
    ally_balance = models.FloatField(default=0)
    contact = models.CharField(max_length=256)
    type = models.IntegerField(choices=TYPES)
    last_update = models.DateTimeField(auto_now=True, db_index=True)

class Area(models.Model):
    name = models.CharField(max_length=256)
    code = models.CharField(max_length=16)

class MaterialType(models.Model):
    MaterialTypes = (
        ('PNG', 'PNG'),
        ('JPG', 'JPG'),
        ('GIF', 'GIF'),
        ('BMP', 'BMP'),
        ('SWF', 'SWF'),
    )
    name = models.CharField(max_length=16, choices=MaterialTypes)

class MaterialTag(models.Model):
    name = models.CharField(max_length=256)

class Material(models.Model):
    StatusTypes = (
        (0, 'NO Audit'),
        (1, 'Pass'),
        (2, 'Reject')
    )
    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    width = models.IntegerField()
    height = models.IntegerField()
    size = models.IntegerField()
    type = models.ForeignKey(MaterialType)
    landingpage = models.CharField(max_length=1024)
    url = models.CharField(max_length=1024)
    status = models.IntegerField(choices=StatusTypes)
    organization = models.ForeignKey(Organization)
    tags = models.ManyToManyField(MaterialTag)
    upload_time = models.DateTimeField(default=datetime.datetime.now())
    creator = models.ForeignKey(User, null=True)
    last_update = models.DateTimeField(auto_now=True, db_index=True)
    reason = models.CharField(max_length=256)
    frequency = models.IntegerField(default=0)


class MediaAttr(models.Model):
    name = models.CharField(max_length=256)

class Media(models.Model):
    MediaType = (
     (0, 'inside'),
     (1, 'outside'),
     (2, 'ally')
    )
    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    attrs = models.ManyToManyField(MediaAttr)
    type = models.IntegerField(choices=MediaType, default=0)
    last_update = models.DateTimeField(auto_now=True, db_index=True)

class PositionAttr(models.Model):
    name = models.CharField(max_length=256)

class Position(models.Model):
    ShowType = (
    (0,'default'),
    (1, 'focus'),
    (2, 'banner'),
    (3, 'others')
    )
    ArrayType = (
    (0, 'horizontal'),
    (1, 'vertical')
    )
    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    attrs = models.ManyToManyField(PositionAttr)
    media = models.ForeignKey(Media)
    width = models.IntegerField()
    height = models.IntegerField()
    size = models.IntegerField()
    min = models.IntegerField()
    max = models.IntegerField()
    types = models.ManyToManyField(MaterialType)
    last_update = models.DateTimeField(auto_now=True, db_index=True)
    show_type = models.IntegerField(choices=ShowType, default=0)
    switch_time = models.IntegerField(default=0)
    arrange_type = models.IntegerField(choices=ArrayType, default=0)
    code = models.TextField(default='')


class Traffic(models.Model):
    BidTypes = (
        (0, 'CPD'),
        (1, 'CPM')
    )
    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    start = models.DateField()
    end = models.DateField()
    position = models.ForeignKey(Position)
    active = models.BooleanField(default=False)
    bid_type = models.IntegerField(choices=BidTypes)
    bid_price = models.FloatField()
    estimated_imp = models.IntegerField()
    estimated_click = models.IntegerField()
    last_update = models.DateTimeField(auto_now=True, db_index=True)



class Resource(models.Model):
    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    start = models.DateField()
    end = models.DateField()
    floor = models.FloatField()       
    traffic = models.ForeignKey(Traffic, related_name='TRAFFIC')
    allow_shared = models.BooleanField(default=True)
    last_update = models.DateTimeField(auto_now=True, db_index=True)
    is_default = models.BooleanField(default=False)
    def set_resource_area(self, args):
        old_objs = self.resourcearea_set.all()
        new_objs = []
        for obj in args:
            ra = ResourceArea(resource=self, area_id=obj)
            new_objs.append(ra)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()
    
    def set_resource_hour(self, args):
        old_objs = self.resourcehour_set.all()
        new_objs = []
        for obj in args:
            rh = ResourceHour(resource=self, hour=obj)
            new_objs.append(rh)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()
            

class ResourceArea(models.Model):
    area = models.ForeignKey(Area)
    resource = models.ForeignKey(Resource)

class ResourceHour(models.Model):
    hour = models.IntegerField()
    resource = models.ForeignKey(Resource)

class Allocation(models.Model):
    BidTypes = (
        (0, 'CPD'),
        (1, 'CPM')
    )
    resource = models.ForeignKey(Resource, related_name='RESOURCE')
    organization = models.ForeignKey(Organization)
    start = models.DateField()
    end = models.DateField()
    type = models.IntegerField(choices=BidTypes)
    price = models.FloatField()
    amount = models.IntegerField()
    priority = models.IntegerField()

    def save(self):
        models.Model.save(self)
        self.resource.save()

class Algorithm(models.Model):
    StatusType=(
     (0,"draft"),
     (1,"release"),
     (2,"abandon"),
    )
    name=models.CharField(max_length=256)
    xml_format=models.TextField()
    code=models.TextField()
    status=models.IntegerField(choices=StatusType)
    passed=models.BooleanField(default=False)
    last_update = models.DateTimeField(auto_now=True, db_index=True)


class Strategy(models.Model):
    ConsumeTypes = (
        (0, 'NORMAL'),
        (1, 'SMOOTH')
    )

    deleted = models.BooleanField(default=False)
    name = models.CharField(max_length=256)
    organization = models.ForeignKey(Organization)
    start = models.DateField()
    end = models.DateField()
    frequency = models.IntegerField()
    total_amount_in = models.IntegerField(default=0)
    total_amount_out = models.IntegerField(default=0)
    total_amount_ally = models.IntegerField(default=0)
    daily_amount_in = models.IntegerField(default=0)
    daily_amount_out = models.IntegerField(default=0)
    daily_amount_ally = models.IntegerField(default=0)
    total_budget_in = models.FloatField(default=0)
    total_budget_out = models.FloatField(default=0)
    total_budget_ally = models.FloatField(default=0)
    daily_budget_in = models.FloatField(default=0)
    daily_budget_out = models.FloatField(default=0)
    daily_budget_ally = models.FloatField(default=0)
    landingpage = models.CharField(max_length=1024)
    consume_type_in = models.IntegerField(choices=ConsumeTypes)
    consume_type_out = models.IntegerField(choices=ConsumeTypes)
    consume_type_ally = models.IntegerField(choices=ConsumeTypes)
    priority = models.IntegerField()
    last_update = models.DateTimeField(auto_now=True, db_index=True)
    algorithm = models.ForeignKey(Algorithm,null=True, default = None)
    parameters=models.TextField(default='')
    def default_strategy(self):
        self.name = 'default'
        self.frequency = 0
        self.total_amount = 0
        self.daily_amount = 0
        self.total_budget = 0
        self.daily_budget = 0
        self.consume_type_in = 0
        self.consume_type_out = 0
        self.consume_type_ally = 0
        self.priority = -10        
        return self
    def set_resource_prices(self, args):
        old_objs = self.resourceprice_set.all()
        new_objs = []
        for obj in args:
            rp = ResourcePrice(strategy=self, resource_id=obj['resource_id'], price=obj['price'])
            new_objs.append(rp)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()

    def set_material_weights(self, args):
        old_objs = self.materialweight_set.all()
        new_objs = []
        for obj in args:
            mw = MaterialWeight(strategy=self, material_id=obj['material_id'], weight=obj['weight'], group=obj['group'])
            new_objs.append(mw)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()

    def set_areas(self, args):
        old_objs = self.strategyarea_set.all()
        new_objs = []
        for obj in args:
            sa = StrategyArea(strategy=self, area_id=obj)
            new_objs.append(sa)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()

    def set_hours(self, args):
        old_objs = self.hour_set.all()
        new_objs = []
        for obj in args:
            hour = Hour(strategy=self, hour=obj)
            new_objs.append(hour)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()
    def set_words(self, args):
        old_objs = self.strategyword_set.all()
        new_objs = []
        for obj in args:
            word = StrategyWord(strategy=self, hotword_id=int(obj["id"]),name=obj["name"])
            new_objs.append(word)
        for obj in old_objs:
            obj.delete()
        for obj in new_objs:
            obj.save()
        self.save()
    

    

class ResourcePrice(models.Model):
    price = models.FloatField()
    resource = models.ForeignKey(Resource)
    strategy = models.ForeignKey(Strategy)

class MaterialWeight(models.Model):
    material = models.ForeignKey(Material)
    group = models.CharField(max_length=256)
    weight = models.IntegerField()
    strategy = models.ForeignKey(Strategy)

class StrategyArea(models.Model):
    area = models.ForeignKey(Area)
    strategy = models.ForeignKey(Strategy)

class Hour(models.Model):
    hour = models.IntegerField()
    strategy = models.ForeignKey(Strategy)

class HotWord(models.Model):    
    name = models.CharField(max_length=256)    
    level = models.IntegerField(default=1)
    parent = models.ForeignKey('self', null=True)
    last_update = models.DateTimeField(auto_now=True)    

class StrategyWord(models.Model):
    name = models.CharField(max_length=256)
    strategy = models.ForeignKey(Strategy)
    hotword=models.ForeignKey(HotWord)

class OperationLog(models.Model):
    operation=models.CharField(max_length=256)
    object = models.CharField(max_length=256)
    object_id=models.IntegerField()
    details=models.TextField()
    time = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User)
    

class PayLog(models.Model):
    organization = models.ForeignKey(Organization)
    in_balance = models.FloatField(default=0)
    out_balance = models.FloatField(default=0)
    ally_balance = models.FloatField(default=0)
    time = models.DateTimeField(auto_now_add=True)
    account = models.ForeignKey(Account)

class CostLog(models.Model):
    organization = models.ForeignKey(Organization)
    balance = models.FloatField(default=0)
    type = models.IntegerField(default=0)
    time = models.DateTimeField(auto_now_add=True)  
    account = models.ForeignKey(Account) 
    resource=models.ForeignKey(Resource) 
    deleted = models.BooleanField(default=False)

# servers

class DecisionServer(models.Model):
    name = models.CharField(max_length=255, unique=True)
    business_url = models.CharField(max_length=1024)
    budget_url = models.CharField(max_length=1024)
    report_url = models.CharField(max_length=1024)
    active = models.BooleanField(default=True)

class MonitorServer(models.Model):
    name = models.CharField(max_length=255, unique=True)
    active = models.BooleanField(default=True)

class SystemLog(models.Model):
    Levels = (
        (0, 'FATAL'),
        (1, 'ERROR'),
        (2, 'WARNING'),
    )

    Types = (
        (-1, 'Unknown'),
        (0, 'BusinessServer'),
        (1, 'DecisionServer'),
        (2, 'MonitorServer'),
        (3, 'ReportServer'),
        (4, 'MaterialServer'),

    )

    level = models.IntegerField(choices=Levels)
    type = models.IntegerField(choices=Types)
    message = models.CharField(max_length=1024)
    time = models.DateTimeField()

# non-realtime report
class DailyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()

class WeeklyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()

class MonthlyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()

class DailyOrganizationReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    organization = models.ForeignKey(Organization)

class WeeklyOrganizationReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    organization = models.ForeignKey(Organization)

class MonthlyOrganizationReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    organization = models.ForeignKey(Organization)

class DailyOrganizationMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    organization = models.ForeignKey(Organization)
    type = models.IntegerField(default=0)

class WeeklyOrganizationMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    organization = models.ForeignKey(Organization)
    type = models.IntegerField(default=0)

class MonthlyOrganizationMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    organization = models.ForeignKey(Organization)
    type = models.IntegerField(default=0)

class DailyMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    media = models.ForeignKey(Media)

class WeeklyMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    media = models.ForeignKey(Media)

class MonthlyMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    media = models.ForeignKey(Media)

class DailyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    type = models.IntegerField(default=0)

class WeeklyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    type = models.IntegerField(default=0)

class MonthlyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    type = models.IntegerField(default=0)

class DailyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    position = models.ForeignKey(Position)

class WeeklyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    position = models.ForeignKey(Position)

class MonthlyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    position = models.ForeignKey(Position)

class DailyStrategyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    strategy = models.ForeignKey(Strategy)

class WeeklyStrategyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    strategy = models.ForeignKey(Strategy)

class MonthlyStrategyReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    strategy = models.ForeignKey(Strategy)

class DailyStrategyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    strategy = models.ForeignKey(Strategy)
    type = models.IntegerField(default=0)

class WeeklyStrategyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    strategy = models.ForeignKey(Strategy)
    type = models.IntegerField(default=0)

class MonthlyStrategyMediaTypeReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    strategy = models.ForeignKey(Strategy)
    type = models.IntegerField(default=0)


class DailyOrganizationMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    organization = models.ForeignKey(Organization)
    media = models.ForeignKey(Media)

class WeeklyOrganizationMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    organization = models.ForeignKey(Organization)
    media = models.ForeignKey(Media)

class MonthlyOrganizationMediaReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    organization = models.ForeignKey(Organization)
    media = models.ForeignKey(Media)

class DailyOrganizationPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    organization = models.ForeignKey(Organization)
    position = models.ForeignKey(Position)

class WeeklyOrganizationPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    organization = models.ForeignKey(Organization)
    position = models.ForeignKey(Position)

class MonthlyOrganizationPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    organization = models.ForeignKey(Organization)
    position = models.ForeignKey(Position)

class DailyStrategyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    strategy = models.ForeignKey(Strategy)
    position = models.ForeignKey(Position)

class WeeklyStrategyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    strategy = models.ForeignKey(Strategy)
    position = models.ForeignKey(Position)

class MonthlyStrategyPositionReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    strategy = models.ForeignKey(Strategy)
    position = models.ForeignKey(Position)

class DailyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    resource=models.ForeignKey(Resource)

class WeeklyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    resource=models.ForeignKey(Resource)

class MonthlyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    resource=models.ForeignKey(Resource)

class DailyStrategyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    date = models.DateField()
    resource=models.ForeignKey(Resource)
    strategy = models.ForeignKey(Strategy)

class WeeklyStrategyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    start = models.DateField()
    end = models.DateField()
    resource=models.ForeignKey(Resource)
    strategy = models.ForeignKey(Strategy)

class MonthlyStrategyResourceReport(models.Model):
    pv = models.IntegerField()
    uv = models.IntegerField()
    click = models.IntegerField()
    cost = models.FloatField()
    month = models.IntegerField()
    resource=models.ForeignKey(Resource)
    strategy = models.ForeignKey(Strategy)
